/****************************************
* 	NDS game 	
* 	Author: team 3		
****************************************/
//include

#include <nds.h> 
#include <nds/arm9/video.h>
#include <nds/arm9/background.h>
#include <nds/arm9/input.h>
#include <nds/arm9/sprite.h>
#include <nds/system.h>
#include <stdio.h>

#include "main.h"

//include sprites
#include "sprite.h" 
#include "Puzzle.h"
#include "tiled_background0.h"
#include "SpriteObject.h"

GameState game_state = PUZZLE;

//u8 stylus_is_over(touchPosition * touchPos, SpriteEntry * sprite) {
//	return (touchPos->px >= sprite->x && touchPos->px <= sprite->x + 15)
//				&& (touchPos->py >= sprite->y && touchPos->py <= sprite->y + 15);
//}

//coord get_stylus_position_relative_to_sprite(touchPosition * touchPos, SpriteEntry * sprite) {
//	coord pos;
//	pos.x = touchPos->px - sprite->x;
//	pos.y = touchPos->py - sprite->y;
//	return pos;
//}
//
//int get_sprite_memory_offset(coord * coords) {
//	return coords->x % 8 + coords->y % 8 * 8 + coords->x / 8 * 64 + coords->y/8 * 128;
//}

// Only works for main engine!
//u8 stylus_is_over_opaque(touchPosition * touchPos, SpriteEntry * sprite) {
//	if (stylus_is_over(touchPos, sprite)) {
//		u8 * pixel = (u8 *)oamGetGfxPtr(&oamMain, sprite->gfxIndex);
//		coord pos = get_stylus_position_relative_to_sprite(touchPos, sprite);
//		int offset = get_sprite_memory_offset(&pos);
//		printf("palette index: %u\n", pixel[offset]);
//		
//		return pixel[offset] != 0;
//	}
//	
//	return 0;
//}
	
u8 sprite_is_over(SpriteEntry * sprite1, SpriteEntry * sprite2) {
	if (sprite1->x < sprite2->x + 16
		&& sprite2->x < sprite1->x + 16
		&& sprite1->y < sprite2->y + 16
		&& sprite2->y < sprite1->y + 16
	) {
		return 1;
	}
	
	return 0;
}

coord get_coords_for_field(Puzzle_Field field) {
	coord coords;
	switch(field) {
		case TOPLEFT:
			coords.x = 10;
			coords.y=10;
			break;
		case TOPRIGHT:
			coords.x = 123;
			coords.y = 10;
			break;
		case BOTTOMLEFT:
			coords.x = 10;
			coords.y = 91;
			break;
		case BOTTOMRIGHT:
			coords.x = 123;
			coords.y = 91;
			break;
		case OUT_OF_BOUNDS:
			coords.x = 255;
			coords.y = 255;
			break;
	}

	return coords;
}

Puzzle_Field get_field_for_coords(coord coords){
	int result;
	// Check top or bottom
	if (coords.y >= 10 && coords.y <= 87) {
		result = TOPLEFT | TOPRIGHT;
	} else if (coords.y >= 91 && coords.y <= 168) {
		result = BOTTOMLEFT | BOTTOMRIGHT;
	} else {
		result = OUT_OF_BOUNDS;
	}

	if (coords.x >= 10 && coords.x <= 119) {
		result &= (TOPLEFT | BOTTOMLEFT);
	} else if (coords.x >= 123 && coords.x <= 232) {
		result &= (TOPRIGHT | BOTTOMRIGHT);
	} else {
		result = OUT_OF_BOUNDS;
	}

	return (Puzzle_Field)result;
}

void puzzle_display(Puzzle * puzzle) {
	for (int i=0 ; i < puzzle->num_entries ; i++) {
		Puzzle_Entry * entry = puzzle->entries[i];
		int length = (entry->size & 0xFF) * 32;

		SpriteObject * s = new SpriteObject(&oamMain, entry->size, SpriteColorFormat_256Color);
		dmaCopy(spriteTiles + entry->offset, s->get_gfx_start_address(), length);
		
		coord coords = get_coords_for_field(entry->start_position);
		s->set_position(coords);
	}
}


/*
   Function: main

   Starts the game

   See Also:

      <initGraphics>
*/
int main() {
	initGraphics();

	SpriteEntry * blok1 = &oamMain.oamMemory[sprite_small_id];

	touchPosition touch;
	consoleDemoInit();
	
	SpriteEntry * moving_sprite = NULL;
	
	Puzzle* puzzle = new Puzzle(2);
	puzzle->add_entry(new Puzzle_Entry(sprite_small_offset, SpriteSize_16x16, TOPLEFT, BOTTOMRIGHT));
	puzzle->add_entry(new Puzzle_Entry(sprite_big_offset, SpriteSize_32x32, BOTTOMRIGHT, TOPRIGHT));

	puzzle_display(puzzle);

	while (1) //infinite loop
	{
		//consoleClear();
		scanKeys();
		u32 keys = keysHeld();
		if(keys & KEY_TOUCH){
			touchRead(&touch);
			
			
			//if (game_state == DRAG) {
			//	if (!moving_sprite) {
			//		// something went wrong.
			//		game_state = PUZZLE;
			//	} else {
			//		// Move the sprite
			//		moving_sprite->x = touch.px;
			//		moving_sprite->y = touch.py;
			//	}				
			//} else {
			//	coord stylus_pos;
			//	stylus_pos.x = touch.px;
			//	stylus_pos.y = touch.py;

			//	if (stylus_is_over_opaque(&touch, blok1)) {
			//		game_state = DRAG;
			//		moving_sprite = blok1;
			//	}
			//}
		} else {
			//game_state = PUZZLE;
		}
		
		swiWaitForVBlank();
		oamUpdate(&oamMain);

	}
	return 0;
}


/*
   Function: initGraphics

   Initializes the background graphics for the game and loads the sprite palette.
   
   Uses:
   - VRAM_A_CR
   - REG_DISPCNT
   - REG_BG0CNT
   - BG_PALETTE
   - BG_TILE_RAM(1)
   - BG_MAP_RAM(0)
   - VRAM_F_MAIN_SPRITE
   - SPRITE_PALETTE
*/

void initGraphics(void){
	// Setup the video modes.
	//initialize vram control registers
	VRAM_A_CR = VRAM_ENABLE | VRAM_A_MAIN_BG;

	//initialize display registers
	REG_DISPCNT = MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_SPR_ACTIVE;

	//initialize main screen background registers
	REG_BG0CNT = BG_32x32 | BG_PRIORITY(0) | BG_COLOR_256 | BG_MAP_BASE( 0 ) | BG_TILE_BASE( 1 ) ;


	//copy palette
	memcpy(BG_PALETTE, tiled_background0SharedPal, tiled_background0SharedPalLen);

	//copy tiles
	memcpy(BG_TILE_RAM(1), tiled_background0Tiles, tiled_background0TilesLen);

	//copy map
	memcpy(BG_MAP_RAM(0), tiled_background0Map, tiled_background0MapLen);


	vramSetBankF(VRAM_F_MAIN_SPRITE);
	lcdMainOnBottom();

	//setup sprites
	oamInit(&oamMain, SpriteMapping_1D_128, false); //initialize the oam
	//u16* gfx = oamAllocateGfx(&oamMain, SpriteSize_16x16,SpriteColorFormat_256Color);//make room for the sprite
	//u16* gfx32 = oamAllocateGfx(&oamMain, SpriteSize_32x32,SpriteColorFormat_256Color);//make room for the sprite


	//dmaCopy(spriteTiles + sprite_small_offset, gfx, sprite_small_length);//copy the sprite
	//dmaCopy(spriteTiles + sprite_big_offset, gfx32, sprite_big_length);//copy the sprite
	dmaCopy(spritePal, SPRITE_PALETTE, spritePalLen); //copy the sprites palette oamEnable(&oamMain);


	//oamSet(&oamMain,sprite_small_id,64,32,0,0,SpriteSize_16x16,SpriteColorFormat_256Color,gfx,0,false,false,false,false,false); 
	//oamSet(&oamMain,1,64,32,0,0,SpriteSize_32x32,SpriteColorFormat_256Color,gfx32,0,false,false,false,false,false); 
}
